#include "src/Jeu.h"
#include <malloc.h>
#include <stdlib.h>
#include "src/Terrain.h"
#include <time.h>

void jeuInit(Jeu *J)
{

	J->pers = initPerso(4 , 4);
	J->ter = initTerrain(J->ter);
	J->Terrain1=intiTerrain1(J->Terrain1);
	J->Terrain2=intiTerrain2(J->Terrain2);
	J->Terrain3=intiTerrain3(J->Terrain3);
    J->nb_Bonus = 0;
	J->Terrain4=intiTerrain4(J->Terrain4);
	J->nb_Zombie = 0;
	J->tab_Zomb=malloc(1*sizeof(Tab_Zombie));
    initialiserTabZombie(J->tab_Zomb);
    initialiserTabProjectile(J->tab_Proj);
    J->nb_Projectile = 0;
    J->score = 0;

}

void jeuLibere(Jeu * J)

{
    libereTerrain(J->ter);
	free(J->tab_Zomb);
}

Terrain *jeuGetTerrainPtr(Jeu * J)
{
	return J->ter;
}

Perso *jeuGetPersoPtr(Jeu * J)
{
    	return J->pers;
}

Terrain * jeuGetCstTerrainPtr(const Jeu * J)
{
    return J->ter;
}

const Perso *jeuGetCstPersoPtr(const Jeu *J )
{
    return J->pers;
}

void jeuActionClavier(Jeu *J, const char touche)
{
	switch(touche)
	{
		case 'g' :
				deplacementPersoGauche(J->pers, J->ter);
				break;
		case 'd' :
				deplacementPersoDroite(J->pers, J->ter);
				break;
		case 'h' :
				deplacementPersoHaut(J->pers, J->ter);
				break;
		case 'b' :
				deplacementPersoBas(J->pers, J->ter);
				break;
        case 'o' :
            switch (getVuePerso(J->pers))
                        {
                            case 'g' :if (deplacementProjectileValide (J->ter, getCoordXPerso(J->pers)-1, getCoordYPerso(J->pers)) == 1)

                                                                {
                                                                     ajouterElementProjectile(J->tab_Proj, J->pers);

                                                                    J->nb_Projectile = J->nb_Projectile + 1;
                                                                }
                                                                break;

                            case 'd' :if (deplacementProjectileValide (J->ter, getCoordXPerso(J->pers)+1, getCoordYPerso(J->pers)) == 1)

                                            {
                                                  ajouterElementProjectile(J->tab_Proj, J->pers);
                                                J->nb_Projectile = J->nb_Projectile + 1;
                                            }
                                            break;

                            case 'h' :if (deplacementProjectileValide (J->ter, getCoordXPerso(J->pers), getCoordYPerso(J->pers)-1) == 1)
                                            {
                                                  ajouterElementProjectile(J->tab_Proj, J->pers);
                                                J->nb_Projectile = J->nb_Projectile + 1;
                                            }
                                            break;

                            case 'b' :if (deplacementProjectileValide (J->ter, getCoordXPerso(J->pers), getCoordYPerso(J->pers)+1) == 1)

                                            {
                                                  ajouterElementProjectile(J->tab_Proj, J->pers);
                                                J->nb_Projectile = J->nb_Projectile + 1;
                                            }
                                            break;

                        }

                break;
	}
}

Bonus * jeuGetCstBonusPtr(const Jeu * J)
{
return J->bonus;
}

//Defilement terrain d'un cran vers la gauche et nouvelle colonne
void defilementTerrain (Jeu *J, char *col)
{
int y, x,i,boucle, x_Zombie, y_Zombie;
boucle =0;

if ( J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)+1]== '#' || J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)+1]== '*' || J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)+1]== '+' )
        {
            if( (J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)+1]== '#' || J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)+1]== '*' || J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)+1]== '+' )&&( J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)-1]== '#' || J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)+1]== '*' || J->ter->tab[getCoordYPerso(J->pers)][getCoordXPerso(J->pers)-1]== '+') )
                {
                    setCoordXPerso(J->pers,getCoordXPerso(J->pers)-1);

                }
            else {deplacementPersoGauche(J->pers, J->ter);}

        }
for (boucle = 0 ; boucle < J->nb_Bonus ; boucle ++)
{
    x_Zombie = getCoordXZombie(getElementTabZombie(J->tab_Zomb, boucle)) ;
    y_Zombie = getCoordYZombie(getElementTabZombie(J->tab_Zomb, boucle)) ;
    if ( J->ter->tab[y_Zombie][x_Zombie+1]== '#' || J->ter->tab[y_Zombie][x_Zombie+1]== '*' || J->ter->tab[y_Zombie][x_Zombie+1]== '+' )
        {
            deplacementZombieGauche((getElementTabZombie(J->tab_Zomb, boucle)), J->ter);

        }
}

if (J->nb_Bonus == 1)
{
i = getCoordXBonus(J->bonus) - 1;
setCoordXBonus(J->bonus, i);
}

for(y=0;y<J->ter->dimY;++y)
{
        J->ter->tab[y][J->ter->dimX] = col[y];


                for(x=1;x<J->ter->dimX;++x)
                {
                        J->ter->tab[y][x] = J->ter->tab[y][x + 1];
                }
}
}

Jeu * ajouterZombie (Jeu * J)
{
    J->nb_Zombie=J->nb_Zombie+1;
//    initZombie (&(J->tab_Zomb[J->nb_Zombie-1]),19,13);
    return J;

}
//void directionzombie(jeu *)
void evolutionZombie (Jeu * J)
{
    int a;
    char dir;
    a=0;

   for (a= 0; a<J->nb_Zombie ; a++ )
    {
    int x_Zombie, y_Zombie, deplacement_ok ;
    int nb_alea;
    dir = getdirectionZombie(getElementTabZombie(J->tab_Zomb, a)) ;
     x_Zombie = getCoordXZombie(getElementTabZombie(J->tab_Zomb, a)) ;
    y_Zombie = getCoordYZombie(getElementTabZombie(J->tab_Zomb, a)) ;
    deplacement_ok = 0 ;

    if (( dir == 'o' ))
    {
        nb_alea = rand() % 4 +1 ;
        switch (nb_alea)
        {
            case 1 :setdirectionZombie ((getElementTabZombie(J->tab_Zomb, a)),'h');
                    dir = 'h';
                break ;
            case 2 :setdirectionZombie ((getElementTabZombie(J->tab_Zomb, a)),'b');
            dir = 'b';
                break ;
            case 3 :setdirectionZombie ((getElementTabZombie(J->tab_Zomb, a)),'d');
            dir = 'd';
                break ;
            case 4 :setdirectionZombie ((getElementTabZombie(J->tab_Zomb, a)),'g');
            dir = 'g';
                break ;
        }
    }


    switch (dir)
    {
        case 'h' :
                deplacement_ok = deplacementZombieValide(J->ter, x_Zombie, y_Zombie - 1);
                if (deplacement_ok == 1 && testvalidezombie (J, getElementTabZombie(J->tab_Zomb, a)) == 0)
                    deplacementZombieHaut(getElementTabZombie(J->tab_Zomb, a), J->ter);
                break;
        case 'b' :
                deplacement_ok = deplacementZombieValide(J->ter, x_Zombie, y_Zombie + 1);
                if (deplacement_ok == 1 && testvalidezombie (J, getElementTabZombie(J->tab_Zomb, a)) == 0)
                    deplacementZombieBas(getElementTabZombie(J->tab_Zomb, a), J->ter);
                break;
        case 'd' :
                deplacement_ok = deplacementZombieValide(J->ter, x_Zombie + 1, y_Zombie);
                if (deplacement_ok== 1&& testvalidezombie (J, getElementTabZombie(J->tab_Zomb, a)) == 0)
                    deplacementZombieDroite(getElementTabZombie(J->tab_Zomb, a), J->ter);
                break;
        case 'g' :
                deplacement_ok = deplacementZombieValide(J->ter, x_Zombie - 1, y_Zombie);
                if (deplacement_ok == 1&& testvalidezombie (J,getElementTabZombie(J->tab_Zomb, a)) == 0)
                    deplacementZombieGauche(getElementTabZombie(J->tab_Zomb, a), J->ter);
                break;
    }
    if (deplacement_ok == 0)
    {   int compt;
    compt =0;
        while (deplacement_ok == 0 )
        {
            if (compt <= 4)
            {
                nb_alea = rand() % 4 +1 ;
                switch (nb_alea)
                {
                    case 1 :
                            deplacement_ok = deplacementZombieValide(J->ter, x_Zombie, y_Zombie - 1);
                            if (deplacement_ok == 1 && testvalidezombie (J, getElementTabZombie(J->tab_Zomb, a)) == 0)
                               {
                                   deplacementZombieHaut(getElementTabZombie(J->tab_Zomb, a), J->ter);
                                    setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'h');
                               }
                                else
                            {
                                setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'o');
                            }

                            break;
                    case 2 :
                            deplacement_ok = deplacementZombieValide(J->ter, x_Zombie, y_Zombie + 1);
                            if (deplacement_ok == 1 && testvalidezombie (J, getElementTabZombie(J->tab_Zomb, a)) == 0)
                            {
                                deplacementZombieBas(getElementTabZombie(J->tab_Zomb, a), J->ter);
                               setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'b');
                            }
                             else
                            {
                                setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'o');
                            }
                            break;
                    case 3 :
                            deplacement_ok = deplacementZombieValide(J->ter, x_Zombie + 1, y_Zombie);
                            if (deplacement_ok == 1 && testvalidezombie (J, getElementTabZombie(J->tab_Zomb, a)) == 0)
                               {
                                   deplacementZombieDroite(getElementTabZombie(J->tab_Zomb, a), J->ter);
                                   setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'d');
                               }
                                else
                            {
                                setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'o');
                            }
                            break;
                    case 4 :
                            deplacement_ok = deplacementZombieValide(J->ter, x_Zombie - 1, y_Zombie) ;
                            if (deplacement_ok == 1 && testvalidezombie (J, getElementTabZombie(J->tab_Zomb, a)) == 0)
                               {
                                    deplacementZombieGauche(getElementTabZombie(J->tab_Zomb, a), J->ter);
                                   setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'g');
                               }
                            else
                            {
                                setdirectionZombie (getElementTabZombie(J->tab_Zomb, a),'o');
                            }
                            break;
            }
            }
            else {deplacement_ok =1;}
            compt = compt +1;
        }



}


}
a++;
}

void evolutionProjectile (Jeu * J)
{

    int a,x_Projectile,y_Projectile;
    int b;
    int dir;
    for (a=0 ; a < J->nb_Projectile; a++)
    {
        dir = getDirectionProjectile(getElementTabProjectile(J->tab_Proj, a));
        x_Projectile = getCoordXProjectile(getElementTabProjectile(J->tab_Proj, a));
        y_Projectile = getCoordYProjectile(getElementTabProjectile(J->tab_Proj, a));
        switch (dir)
        {

            case 'h' :


                for (b=0 ; b< J->nb_Zombie; b++)
                {
                    if ( x_Projectile == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && (y_Projectile-1)== getCoordYZombie(getElementTabZombie(J->tab_Zomb, b) ))
                    {
                        setVieZombie(getElementTabZombie(J->tab_Zomb, b), getVieZombie(getElementTabZombie(J->tab_Zomb, b) )-1) ;
                        suprimerElementProjectile (J->tab_Proj, a);
                        J->nb_Projectile = J->nb_Projectile - 1;
                        break;
                    }
                }


                    if (deplacementProjectileValide(J->ter , x_Projectile , y_Projectile - 1) == 1)
                    {
                        deplacementProjectileHaut(getElementTabProjectile(J->tab_Proj, a));
                    }
                    else
                    {
                        suprimerElementProjectile (J->tab_Proj, a);
                        J->nb_Projectile = J->nb_Projectile - 1;

                    }


                break;

            case 'b' :

                for (b=0 ; b< J->nb_Zombie; b++)
                {
                    if ( x_Projectile == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && (y_Projectile+1)== getCoordYZombie(getElementTabZombie(J->tab_Zomb, b))  )
                    {
                        setVieZombie(getElementTabZombie(J->tab_Zomb, b), getVieZombie(getElementTabZombie(J->tab_Zomb, b)) -1) ;
                        suprimerElementProjectile (J->tab_Proj, a);
                        J->nb_Projectile = J->nb_Projectile - 1;
                        break;
                    }

                }


                if (deplacementProjectileValide(J->ter , x_Projectile , y_Projectile + 1) ==1)
                {
                    deplacementProjectileBas(getElementTabProjectile(J->tab_Proj, a));
                }
                else
                {
                    suprimerElementProjectile (J->tab_Proj, a);
                   J->nb_Projectile = J->nb_Projectile - 1;
                }


                break ;

            case 'd' :

                for (b=0 ; b< J->nb_Zombie; b++)
                {
                    if ( (x_Projectile+1) == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && y_Projectile== getCoordYZombie(getElementTabZombie(J->tab_Zomb, b)) )
                    {
                        setVieZombie(getElementTabZombie(J->tab_Zomb, b), getVieZombie(getElementTabZombie(J->tab_Zomb, b)) -1) ;
                        suprimerElementProjectile (J->tab_Proj, a);
                        J->nb_Projectile = J->nb_Projectile - 1;
                        break;
                    }

                }


                if (deplacementProjectileValide(J->ter , x_Projectile +1, y_Projectile) ==1)
                {
                            deplacementProjectileDroite(getElementTabProjectile(J->tab_Proj, a));
                }
                else
                {
                    suprimerElementProjectile (J->tab_Proj, a);
                    J->nb_Projectile = J->nb_Projectile - 1;

                }


                break ;

            case 'g' :

                for (b=0 ; b< J->nb_Zombie; b++)
                {
                    if ( (x_Projectile-1) == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && y_Projectile== getCoordYZombie(getElementTabZombie(J->tab_Zomb, b)) )
                    {
                        setVieZombie(getElementTabZombie(J->tab_Zomb, b), getVieZombie(getElementTabZombie(J->tab_Zomb, b)) -1) ;
                        suprimerElementProjectile (J->tab_Proj, a);
                        J->nb_Projectile = J->nb_Projectile - 1;
                        break;
                    }

                }

                if (deplacementProjectileValide(J->ter , x_Projectile -1 , y_Projectile) ==1)
                {
                            deplacementProjectileGauche(getElementTabProjectile(J->tab_Proj, a));
                }
                else
                {
                    suprimerElementProjectile (J->tab_Proj, a);
                    J->nb_Projectile = J->nb_Projectile - 1;
                }


                break ;

    }
}
}



void persovsZombie(Jeu * J)
{
    int a;
    Zombie * zomb= malloc(1*sizeof(Zombie));

    for (a=0 ;a< J->nb_Zombie ; a++)
{
    zomb = getElementTabZombie(J->tab_Zomb, a);
    if ((J->pers->x_Perso == zomb->x_Zombie) && (J->pers->y_Perso == zomb->y_Zombie))
    {
        J->pers->x_Perso = J->pers->x_Perso -1;
        J->pers->vie_Perso = J->pers->vie_Perso -1;
        a=J->nb_Zombie+1;
    }
}
}

int testvalidezombie (Jeu * J, Zombie *zomb)
{
    int b;
    int Zombiedevant;
    Zombiedevant = 0;
        for (b=0; b<J->nb_Zombie; b++)

            {
                switch ( getdirectionZombie (zomb))
                {
                    case 'h' : if ( getCoordXZombie(zomb) == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && (getCoordYZombie(zomb) -1) == getCoordYZombie(getElementTabZombie(J->tab_Zomb, b)))
                                {
                                    Zombiedevant = 1;
                                }
                        break;
                    case 'b' : if ( getCoordXZombie(zomb) == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && (getCoordYZombie(zomb) +1) == getCoordYZombie(getElementTabZombie(J->tab_Zomb, b)))
                                {
                                    Zombiedevant = 1;
                                }
                        break;
                    case 'd' : if ( (getCoordXZombie(zomb)+1) == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && getCoordYZombie(zomb)  == getCoordYZombie(getElementTabZombie(J->tab_Zomb, b)))
                                {
                                    Zombiedevant = 1;
                                }
                        break;
                    case 'g' : if ( (getCoordXZombie(zomb)-1) == getCoordXZombie(getElementTabZombie(J->tab_Zomb, b)) && getCoordYZombie(zomb) == getCoordYZombie(getElementTabZombie(J->tab_Zomb, b)) )
                                {
                                    Zombiedevant = 1;
                                }
                        break ;
                }


        }
return Zombiedevant;
}

void spawnBonus (Jeu * J)
{
char c;
int spawn_ok, nb_alea;
// dimy = J->ter->dimY;
spawn_ok = 0 ;
while (spawn_ok == 0)
{
nb_alea = rand() % 15 ;
c = terrainGetCharCoord (J->ter, J->ter->dimX,nb_alea);
if (c != '#' && c != '*' && c != '+' )
spawn_ok = 1;
}
J->bonus = initBonus (J->ter->dimX -1, nb_alea , 'b');
J->nb_Bonus = 1;

}

void persovsBonus(Jeu * J)
{
if ((J->pers->x_Perso == J->bonus->x_Bonus) && (J->pers->y_Perso == J->bonus->y_Bonus))
{
J->pers->vie_Perso = J->pers->vie_Perso + 1;
detruireBonus (J->bonus);
J->nb_Bonus= 0;
}
}

void defilementcolonnePerso (Jeu * J)
{
    int x,y;
    char c;
    x = getCoordXPerso(J->pers);
    y = getCoordYPerso(J->pers);
    c = terrainGetCharCoord (J->ter, x,y );

    if (c == '#' || c == '+' )
    {
        setCoordXPerso(J->pers, x - 1);
    }
}


void detruireZombie (Tab_Zombie *zomb, int a)
{
  suprimerElement(zomb, a);
}
